package com.enlorenz.core.queue.transfer;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import com.enlorenz.common.util.DataDetUtils;
import com.enlorenz.core.queue.transfer.exception.MessageQueueException;

/**
 * 抽象的消息队列
 * 实现了消息队列的部分方法
 * @author lcb
 */
public abstract class AbstractMessageQueue<T> implements MessageQueue<T>{
	//同步锁
	protected Object synKey=new Object();
	//队列数量限制
	private Integer limitSize;
	//队列名称
	private String name;
	//最近的进入时间
	protected Date lastInDate=null;
	//最近的离开时间
	protected Date lastOutDate=null;
	//消息中间列表，使用LinkedList提高数据操作得效率
	protected List<T> messageList=new LinkedList<T>();
	
	public String toString(){
		return String.format("队列名:[%s]:队列数量:[%s]:限制大小:[%s]",
				this.getName(),this.size(),this.getLimitSize());
	}
	
	/**
	 * 队列大小
	 */
	@Override
	public int size(){
		return messageList.size();
	}
	
	/**
	 * 设置队列名
	 * @param name
	 */
	@Override
	public void setName(String name){
		this.name=name;
	}
	
	/**
	 * 获取队列名
	 * @return
	 */
	@Override
	public String getName(){
		return this.name;
	}
	
	/**
	 * 在加入Message之后
	 */
	protected abstract void doAfterAdd();
	
	/**
	 * 在object为空之后做的事情
	 */
	protected abstract T doObjectWhenListIsEmpty();

	/**
	 * 在list为空之后做的事情
	 */
	protected abstract List<T> doListWhenListIsEmpty();
	
	
	/**
	 * 放入消息集合
	 * @param collection 消息数据
	 */
	@Override
	public void addMsgColl(Collection<T> collection){
		if(DataDetUtils.isCollectionEmpty(collection)){
			return;
		}
		for(T t:collection){
			addMsg(t);
		}
	}
	
	@Override
	public void addMsg(T msg) {
		if(null == msg){
			throw new MessageQueueException(this.getName(),
					String.format("传入队列[%s]的消息为空"
							, this.getName()));
		}
		synchronized(synKey)
		{ 
			//如果设置了队列大小限制，则需要校验是否超过限制
			if(null!=limitSize&&size()>limitSize){
				throw new MessageQueueException(this.getName(),
						String.format("超过队列[%s]大小限制[%s]"
								,this.getName(),limitSize));
			}
			messageList.add(msg); 
			lastInDate=new Date();
			doAfterAdd();
		}
	}
	
	/**
	 * 获取最近的消息进入时间
	 * @return
	 */
	@Override
	public Date getDateOfLastestInput(){
		return lastInDate;
	}
	
	/**
	 * 获取最近的消息离开时间
	 * @return
	 */
	@Override
	public Date getDateOfLastestOutput(){
		return lastOutDate;
	}
	
	/**
	 * 设置限制长度
	 */
	@Override
	public void setLimitSize(Integer limitSize){
		this.limitSize=limitSize;
	}
	
	/**
	 * 获取限制长度
	 * @return
	 */
	@Override
	public Integer getLimitSize(){
		return this.limitSize;
	}
	
	/**
	 * 获取一个消息
	 * @return
	 */
	protected T popMessage(){
		//记录获取的时间
		lastOutDate=new Date();
		
		return messageList.remove(0);
	}
	
	/**
	 * 获取一个消息列表
	 * @return
	 */
	protected List<T> popMessageList(){
		//记录获取的时间
		lastOutDate=new Date();
		
		List<T> outputList=new ArrayList<T>(messageList.size());
		outputList.addAll(messageList);
		messageList.clear();
		return outputList;
	}
	
	/**
	 * 获取消息
	 */
	@Override
	public T getMsg() {
		T message=null;
		synchronized (synKey) {
			if (!messageList.isEmpty()) {
				//获取一个消息
				message = popMessage();
			}else{
				//如果是空的消息该如何处理
				message = doObjectWhenListIsEmpty();
			}
		}
		return message;
	}
	
	/**
	 * 获取消息列表
	 */
	@Override
	public Collection<T> getMsgColl() {
		List<T> outputList=null;
		synchronized (synKey) {
			if (!messageList.isEmpty()) {
				//不为空的消息该如何处理
				outputList=popMessageList();
			}else{
				//如果是空的消息该如何处理
				outputList=doListWhenListIsEmpty();
			}
		}
		return outputList;
	}
}
